Implement Semantic HTML5 Landmark Elements
On this page
Intro to Semantic Landmark Elements
In addition to headings, HTML Landmark elements like header, nav, footer, main, aside and section are another important aspect of giving our pages structure.
These landmark elements create signposts around major sections of our page content and are a great alternative to using only generic divs!
Browse through MDN’s HTML elements reference to see what elements are available that you could incorporate into your projects.
Examining the Listing Detail Page
When we inspect the Listing Detail page rendered in the browser with DevTools, we can see that there’s a nav element used as part of the global Header, but only divs for the rest of the content.
There are divs with ids of “header”, “main”, and “footer” that are all candidates to be replaced by their semantic counterparts.
There should only be one main landmark, located at the top level of a page with other landmarks nested inside of it.
Analyze Landmarks with Axe DevTools
The Axe DevTools browser extension includes rules that will identify issues with page landmarks.
Install the extension for Chrome or Firefox and it will be added as a tab in the DevTools.
Open the Axe DevTools extension and click the “Scan ALL of my page” button.
There are a lot of issues on this page related to landmarks!
Scrolling through Axe DevTools will give us more information about the issues it finds.
One thing to note is that these landmark issues are tagged as “best practice”. While it is true that they aren’t strictly required, they are still really helpful to fix where you can. They are worth implementing, although WCAG violations should be prioritized first.
Note that Axe DevTools took issue with our Portal heading not being in a landmark. We’ll come back to this in a moment.
Video Transcript
When we're in assistive technology, it's really nice to be able to navigate by headings. That's not the only thing that we can add for semantic structure. We have quite a few things actually, but there's another big area of this, which is landmark elements in HTML5. We got new elements that we can use such as header, nav, footer, main section aside.
There's a bunch of them and they're awesome. So what they do is create sort of a, a series of signposts around major sections of content. And we can see a few sections of content on this page, including our navigation, which our navigation is marked up with a nav element. So we have one landmark on the page.
So. We have another one that we could add here for our header. So I mentioned there is a, an element called header. You may have seen it before and when it's what's called top level. So it's, you know, from within our body, there's no other landmarks wrapping it. If we have a header element, it becomes our header banner.
And that is a top level landmark. That is really common. If you have header content on your page, most websites do. As a sibling. So neighboring that we also have our main element and there's some CSS here that's making our header and our main overlap that's okay. But from a content perspective, when you kind of peel away the styles, these are siblings.
And so our main content is a great candidate to convert into a main. And there should be one main, it should be top level. And it's going to mark all of our main content and we can have additional landmarks nested inside of there. And then footer, our footer is pretty bare bones at the moment. And we haven't gotten our marketing team in there quite yet to go and add a bunch of links and helpful things.
But this top level footer is what we call content info when we mark it up with a header or sorry, with a footer element. So I think that's some changes we could make right away to add more semantic structure to this page.
So I'm going to show you another tool that you might come across. You may have already.
Where landmarks come into play. So axe dev tools I've got installed in my developer tools already. It's available for Chrome Firefox edge, I believe. And so with axe, I'm going to scan this page. Let's zoom out slightly. And so when I run this, it gives me a number of results that talk about landmarks. So documents should have one main landmark, all page content should be contained by landmarks.
So we've got some content in here that really should be part of landmark elements. We have one bit of a pickle with our portal routes, so we've got our heading the, of our h1 that now is. In that escape hatch, it's not marked up in the landmark. So often I'll have to think about that one. How are we going to solve that?
Cause our our header is going to happen a bit further down our, our Dom tree, the way I had planned at least. But we've got some of these related landmark results in the Axe extension, and I will call your attention to the fact that these come up as what's called best practice results. So when you've got a bunch of accessibility issues, You have to prioritize them somehow.
And so just so that you are, you know, kind of what sets these landmark issues apart is that they are marked as best practice. So they're not explicitly required, but they are really helpful. And so you might tackle these, like if you have a bunch of critical violations for accessibility, you might do those first and then do landmarks.
I mean, if you can do all of the things, all the suggestions. By all means do it. But I have seen these come up where teams, like they kind of miss that best practice label. So I wanted to draw your attention to that.
Implement Top Level Landmarks
For major content areas of our application, we want to add top-level landmarks that act as a content navigation mechanism in Assistive Technologies. Top level landmarks are ones that are not nested inside of any other landmarks.
HTML5 header, main, footer, and aside are all top-level landmarks. header and footer can also be used for content nested inside of main and section.
Adding main and footer Landmarks
Open up App.js in your editor, where the high-level code of the CampSpots application lives.
Right away we see “main” and “footer” divs that can be replaced.
Here’s the before, with generic div elements:
// inside App.js
export function App() {
return <>
<Header />
<div id="main">
<Router>
...
</Router>
</div>
<div id="footer">
</div>
</>
}And here’s the after, with more semantic landmark elements:
// inside App.js
export function App() {
return <>
<Header />
<main id="main">
<Router>
...
</Router>
</main>
<footer id="footer">
</footer>
</>
}Adding the header Landmark
We can also update our Header component to use the semantic landmark element.
Inside of components/header.js, replace the outer div with the <header> banner element:
// components/header.js
const Header = () => {
return (
<header id="header">
<div id="header-nav">
...
</div>
</header>
)
}Now when we check our work in the browser, we can see the semantic elements as expected.
The Portal Header Issue
As Axe DevTools reported, we still have an issue of the H1 we passed into our portal component not being inside of a landmark.
Even though we changed the site-wide header to use the header element, our h1 is being rendered outside of it. As noted earlier, it is technically not a violation for an H1 to not have a landmark wrapped around it (even though axe DevTools classifies it as a best practice and “moderate”).
We know our site has a healthy heading structure, which has a user impact that I think is more important than doing something to satisfy a tool.
Ultimately, the decision is up to you! You might need to get creative with solutions when faced with architecture constraints. Consider user impact and test with screen reader users to know for sure whether a solution poses a problem or not.
The best accessibility practice doesn’t always emerge immediately when you go to solve an issue. The best solution might take time and experimentation to emerge in your web application.
Highlight Landmarks with Accessibility Insights
Coming back to the browser, let’s check our work with the Landmarks tool from the Accessibility Insights extension.
The extension draws borders around the different landmark areas and adds labels to the top right corners.
The “banner” and “main” landmarks have some overlap due to styling, but the “navigation” landmark contains only the MegaNav. The “contentinfo” landmark is at the bottom of the page.
The “banner” landmark name comes from the top-level <header>'s implicit ARIA role, and the “contentinfo” name from the top-level <footer>'s implicit ARIA role.
Using proper elements when grouping content sections in our markup makes it easier to jump around by landmarks in a screen reader.
Even though we’ve been looking at the Listing Detail page, our updates were pretty high up in the application structure and multiple pages have benefited from the changes.
Video Transcript
So let's go over to our code and I'm going to come over to app.js, because that is where a lot of our like kind of top level code lives.
So here's something I could change right away. So div id=main.
And I did command D to select the opening and closing div tags. I could change that to a main element, same with our footer. It has divs inside so I can't do the little multi-select trick, but I could say footer and change the closing tag.
So our main and our footer now have landmarks wrapping them. And I'm going to leave these IDs here for footer ID, footer and main ID main. We do have some CSS that matches those so I can seamlessly swap out this tag, let the ID selectors match in our CSS. I don't have to open that can of worms, right?
The second the IDs can also be useful if we're going to add skip links or something. We aren't working on that quite yet. However, I will sort of, you know, foreshadow that having IDs for these major landmarks can be useful for skip links. So I'm going to hit save. We also have our header component.
So if I go over to our components directory and go to header, this is where div ID header lives. Now our first option, you know, what we talked about was creating header ID header. So this top level header will become our header banner. I'm going to come back over to our browser. I'll hit refresh, come over to elements.
And now within our header ID header, now we've got header main footer. We still have this issue of our portal route though. It's outside of our header. So man, that is, you know, we're kind of like we fix one problem and then we introduce another problem. Classic.
So I guess thinking through some options for our portal route, I mean, ideally it would get injected into. The header element, like that's where it really should live. That's where that h1 should be to be all neat and tidy, but the way that react wanted to give us this escape hatch at least for this, that technique, we had to put it outside of our app route.
So I mean, there's no reason why we can't have multiple headers. I mean, if they're both top level. Main is the one that we, we can only have one. So I think for kind of an initial idea of like, we just need to do something and try it. I would probably say that our portal route could instead of a div, it could inject a header.
We know that that's going to be super high up in the Dom. It's going to have header type content in it, I guess if we don't know for sure that the portal route. What is going to be injected. Maybe we could let the content drive what it's going to be. So for example, on page listing detail, I mean, I could fix the warning by just wrapping this in a header in here and that would potentially fix it.
Then every time header portal gets used, you'd have to remember to go and put it in a header element, which. Folks may or may not may or may not remember that. So think about this some more. I think for the time being I might go over here to header portal. It's like, what's, what's the best solution here.
I think having one header landmark would be the best since this result. I'm sort of thinking through options here. Since this result from axe dev tools, I'm gonna refresh that I'll make this slightly bigger since this is a best practice. This is not an accessibility violation for this portal route.
It's technically not a failure. So I might make the choice in this moment to live with it. And your team might too you know, we have to choose between trade-offs and sometimes you just are like between a rock and hard place. And so I think with more. You know, more time, more, more experimentation in your web application, you might come up with like the ultimate solution, but it might not emerge right away.
You know, sometimes it can take some time. So we have to pick the best option from the things in front of us. So right now, I think rather than have two header landmarks, I'm going to let this h1 live outside of the landmark and choose to not follow this best practice rule for this one, heading. Sort of kick the can down the road.
Cause our heading structure is looking really good. Like this is solid and users have reported that they use headings a lot more than they use landmarks. So we have to kind of check, like we don't always want to make decisions to like satisfy a tool. We want to think about the user experience and what is the most important thing to do.
And I would say in this case, having a healthy hunting structure is more important than trying to satisfy this best practice rule.
So coming back to our browser, I am going to show you another version or another tool within accessibility insights. We saw headings so far, let's look at landmarks. So now we've got it showing navigation, landmark banner and mainland mark are kind of overlapping here because of our CSS style.
That's how we got this pretty image kind of all the way up at the top. Even though we have a header kind of proceeding it in our page source order. If I scroll down, we've got our content info or our footer landmark down here at the bottom. So we have our kind of base requirements for using landmarks, which is having major content sections marked up so that we have these kind of signposts to make it easier to jump around by landmarks.
There's more that we can do within specific landmarks. So within banner, for example, we've got a navigation landmark. Within main. We have some sections that we could mark up further. So let's go play with that. And the cool thing about what we've added so far with header main and footer is that those are pretty high up in our, our applications.
So every page on the site now benefits from all of these landmarks. So our homepage, our events page our about page, like all of these pages now, because they are using that same. Page structure you know, page components or app components. They benefit from some of that higher level semantic structure that we've added, which is really cool.


